package com.ai.ms;

import com.sun.rowset.internal.Row;
import javafx.scene.control.ComboBox;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

public class MainFrame extends JFrame implements ActionListener {

    int ROW = 20; //行数
    int COL = 20; //列数
    int[][] data = new int[ROW][COL];//存放数据
    JButton[][] btns = new JButton[ROW][COL];
    int LAND_MINE_COUNT = 20; //雷的总数
    int LAND_MINE_CODE = -1; //表示是雷
    int unopened = ROW * COL; //未开格子数
    int opened = 0; //已开格子数
    int seconds = 0; //时钟计数

    ImageIcon windowIcon = new ImageIcon("src/main/resources/icon/icon.png");
    ImageIcon bannerIcon = new ImageIcon("src/main/resources/imgs/banner.png");
    ImageIcon guessIcon = new ImageIcon("src/main/resources/imgs/guess.png");
    ImageIcon bombIcon = new ImageIcon("src/main/resources/imgs/bomb.png");
    ImageIcon failIcon = new ImageIcon("src/main/resources/imgs/fail.png");
    ImageIcon winIcon = new ImageIcon("src/main/resources/imgs/win.png");
    ImageIcon winFlagIcon = new ImageIcon("src/main/resources/imgs/win_flag.png");
    JButton bannerBtn = new JButton(bannerIcon);
    JLabel label1 = new JLabel("待开：" + unopened);
    JLabel label2 = new JLabel("已开：" + opened);
    JLabel label3 = new JLabel("用时：" + seconds + "s");
    Timer timer = new Timer(1000, this);

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("选择游戏难度(C)");
    JMenuItem[] menuItems = new JMenuItem[4];

    public MainFrame() {
        this.setSize(900, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new BorderLayout());
        this.setResizable(false);
        this.setIconImage(windowIcon.getImage());
        setHeader();
        addLandMine();
        setButtons();
        start();
        timer.start();
        this.setVisible(true);
    }

    /**
     * 设置窗口的菜单栏
     */
    private void setMenuBar() {
        String[] levels = {"初级", "中级", "高级", "自定义"};
        for (int i = 0; i < 4; i++) {
            menuItems[i] = new JMenuItem(levels[i]);
            menuItems[i].addActionListener(this);
            menu.add(menuItems[i]);
        }
        menuBar.add(menu);
        menuBar.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
        menuBar.setBackground(Color.WHITE);
        this.setJMenuBar(menuBar);
    }

    /**
     * 设置头部的Banner以及状态栏的布局和控件
     */
    private void setHeader() {
        JPanel panel = new JPanel(new GridBagLayout());

        GridBagConstraints bannerBtnConstraints = new GridBagConstraints(0, 0, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0);
        GridBagConstraints label1Constraints = new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
        GridBagConstraints label2Constraints = new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
        GridBagConstraints label3Constraints = new GridBagConstraints(2, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);

        bannerBtn.addActionListener(this);

        label1.setOpaque(true);
        label1.setBackground(Color.white);
        label1.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));

        label2.setOpaque(true);
        label2.setBackground(Color.white);
        label2.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));

        label3.setOpaque(true);
        label3.setBackground(Color.white);
        label3.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));

        bannerBtn.setOpaque(true);
        bannerBtn.setBackground(Color.white);
        bannerBtn.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));


        panel.add(bannerBtn, bannerBtnConstraints);
        panel.add(label1, label1Constraints);
        panel.add(label2, label2Constraints);
        panel.add(label3, label3Constraints);

        this.add(panel, BorderLayout.NORTH);
        setMenuBar();
    }

    /**
     * 埋雷并计算周边雷的数量
     */
    private void addLandMine() {
        Random rand = new Random();

        for (int i = 0; i < LAND_MINE_COUNT; ) {
            int r = rand.nextInt(ROW), c = rand.nextInt(COL);
            if (data[r][c] != LAND_MINE_CODE) {
                data[r][c] = LAND_MINE_CODE;
                i++;
            }
        }

        //计算周边的雷的数量 -- 作者的这个算法写得有些巧妙
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                if (data[i][j] == LAND_MINE_CODE) continue;
                int tempCount = 0;
                if (i > 0 && j > 0 && data[i - 1][j - 1] == LAND_MINE_CODE) tempCount++;
                if (i > 0 && data[i - 1][j] == LAND_MINE_CODE) tempCount++;
                if (i > 0 && j < 19 && data[i - 1][j + 1] == LAND_MINE_CODE) tempCount++;
                if (j > 0 && data[i][j - 1] == LAND_MINE_CODE) tempCount++;
                if (j < 19 && data[i][j + 1] == LAND_MINE_CODE) tempCount++;
                if (i < 19 && j > 0 && data[i + 1][j - 1] == LAND_MINE_CODE) tempCount++;
                if (i < 19 && data[i + 1][j] == LAND_MINE_CODE) tempCount++;
                if (i < 19 && j < 19 && data[i + 1][j + 1] == LAND_MINE_CODE) tempCount++;
                data[i][j] = tempCount;
            }
        }
    }

    /**
     * 启动时创建并添加按钮
     */
    private void setButtons() {
        Container container = new Container();
        container.setLayout(new GridLayout(ROW, COL));

        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                JButton btn = new JButton(guessIcon);
                btn.addActionListener(this);
                container.add(btn);
                btns[i][j] = btn;
            }
        }

        this.add(container, BorderLayout.CENTER);
    }

    /**
     * 事件响应，点击按钮和时钟都会触发这个方法
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof Timer) {
            seconds++;
            label3.setText("用时：" + seconds + "s");
            timer.start();
            return;
        }

        AbstractButton item = (AbstractButton) e.getSource();
        if ("初级".equals(item.getText())) {
            // 窗格数调整为8*8，炸弹数调整为 8
            System.out.println("初级");
            ROW = COL = 8;
            LAND_MINE_COUNT = 8;
            start();
        } else if ("中级".equals(item.getText())) {
            // 窗格数调整为16*16，炸弹数调整为 16
            ROW = COL = 16;
            LAND_MINE_COUNT = 16;
            start();
        } else if ("高级".equals(item.getText())) {
            // 窗格数调整为20*20，炸弹数调整为 20
            ROW = COL = 20;
            LAND_MINE_COUNT = 16;
            start();
        } else if ("自定义".equals(item.getText())) {
            // 弹出选项框，让用户选择窗格大小，以及炸弹数量
        }

        JButton btn = (JButton) e.getSource();
        if (btn.equals(bannerBtn)) {
            start();
            return;
        }

        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                if (btn.equals(btns[i][j])) {
                    if (data[i][j] == LAND_MINE_CODE) {
                        lose();
                    } else {
                        openCell(i, j);
                        checkWin();
                    }
                    return;
                }
            }
        }
    }

    /**
     * 赢了游戏的处理
     */
    private void checkWin() {
        int count = 0;
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                if (btns[i][j].isEnabled()) count++;
            }
        }
        if (count == LAND_MINE_COUNT) {
            timer.stop();
            for (int i = 0; i < ROW; i++) {
                for (int j = 0; j < COL; j++) {
                    if (btns[i][j].isEnabled()) {
                        btns[i][j].setIcon(winFlagIcon);
                    }
                }
            }
            bannerBtn.setIcon(winIcon);
            JOptionPane.showMessageDialog(this, "你赢了, Yeah！\n点击Banner重新开始", "赢了", JOptionPane.PLAIN_MESSAGE);
        }
    }

    /**
     * 输掉游戏的处理
     */
    private void lose() {
        timer.stop();
        bannerBtn.setIcon(failIcon);
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                if (btns[i][j].isEnabled()) {
                    JButton btn = btns[i][j];
                    if (data[i][j] == LAND_MINE_CODE) {
                        btn.setEnabled(false);
                        btn.setIcon(bombIcon);
                        btn.setDisabledIcon(bombIcon); // 设置按钮无效状态下的图标
                    } else {
                        btn.setIcon(null);
                        btn.setEnabled(false);
                        btn.setOpaque(true);
                        btn.setText(data[i][j] + "");
                    }
                }
            }
        }
        Object[] options = {"再来一局", "确定"};
        int optionResult = JOptionPane.showOptionDialog(this, "好可惜，暴雷了...\n点击Banner可重新开始", "暴雷啦", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
        if (optionResult == 0) {
            start();
        }
    }

    /**
     * 打开格子的过程
     *
     * @param i 所在行
     * @param j 所在列
     */
    private void openCell(int i, int j) {
        JButton btn = btns[i][j];
        if (!btn.isEnabled()) return; // ?

        btn.setIcon(null);
        btn.setEnabled(false);
        btn.setOpaque(true);
        btn.setBackground(Color.WHITE);
        if (data[i][j] == 0) {
            btn.setText("");
        } else {
            btn.setText(data[i][j] + "");
        }
        countOpened();

        if (data[i][j] == 0) {
            if (i > 0 && j > 0 && data[i - 1][j - 1] == 0) openCell(i - 1, j - 1);
            if (i > 0 && data[i - 1][j] == 0) openCell(i - 1, j);
            if (i > 0 && j < 19 && data[i - 1][j + 1] == 0) openCell(i - 1, j + 1);
            if (j > 0 && data[i][j - 1] == 0) openCell(i, j - 1);
            if (j < 19 && data[i][j + 1] == 0) openCell(i, j + 1);
            if (i < 19 && j > 0 && data[i + 1][j - 1] == 0) openCell(i + 1, j - 1);
            if (i < 19 && data[i + 1][j] == 0) openCell(i + 1, j);
            if (i < 19 && j < 19 && data[i + 1][j + 1] == 0) openCell(i + 1, j + 1);
        }
    }

    /**
     * 打开计数加1
     */
    private void countOpened() {
        opened++;
        unopened--;
        label1.setText("待开：" + unopened);
        label2.setText("已开：" + opened);
    }

    /**
     * 1.数据清零；2.按钮恢复状态；3.重新启动时钟
     */
    private void start() {
        //恢复数据和按钮
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                data[i][j] = 0;
                btns[i][j].setBackground(new Color(211, 211, 211));
                btns[i][j].setEnabled(true);
                btns[i][j].setText("");
                btns[i][j].setIcon(guessIcon);
            }
        }

        //状态栏恢复
        unopened = ROW * COL;
        opened = 0;
        seconds = 0;
        label1.setText("待开：" + unopened);
        label2.setText("已开：" + opened);
        label3.setText("用时：" + seconds + "s");
        bannerBtn.setIcon(bannerIcon);

        //重新启动
        addLandMine();
        timer.start();
    }

}
